﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Ue.Qcdz.Domain.ContentTypes;
using Ue.Framework.Collections;

namespace Ue.Qcdz.Domain.TreeViews
{
    public class TreeView : Ue.Infrastructure.DomainBase.EntityBase
    {
        #region 构造和字段

        private IList<TreeNode> cacheNodes;
        private object lockThis = new object();

        public TreeView()
            : this(null) { }

        public TreeView(object key)
            : base(key)
        {
            this.cacheNodes = new List<TreeNode>();
        }


        //public TreeView(ContentType contentType)
        //    : this(null, contentType) { }

        //public TreeView(object key,ContentType contentType)
        //    :base(key)
        //{
        //    if (contentType == null)
        //    {
        //        throw new ArgumentNullException("contentType");
        //    }

        //    this.ContentType = contentType;
        //    this.cacheNodes = new List<TreeNode>();
        //}

        #endregion

        #region 公共属性

        //public ContentType ContentType { get; private set; }

        public string Name { get; set; }

        public string Description { get; set; }

        internal IEnumerable<TreeNode> Items
        {   //需要使用ToList把集合映射到一个新对象中，因为在合用过程中this.cacheNodes是可以通过AddNode改变数量的，
            //所以，如果在foreach Items时调用了AddNode那么集合就会改变，就会报错。所以这里需要把集合映射到新对象
            get { return this.cacheNodes.ToList(); }
        }

        public virtual IEnumerable<TreeNode> ChildNodes
        {
            get
            {
                return this.Items
                    .Where(item => item.Parent == null)
                    .OrderBy(item => item.DisplayOrder).ToList();
            }
        } 

        #endregion

        #region Add / Remove

        public virtual void AddNode(TreeNode node)
        {
            this.CheckNode(node);


            if (node.Parent != null && !this.cacheNodes.Contains(node.Parent))
            {
                if (node.Parent != null && !this.cacheNodes.Contains(node.Parent))
                {
                    this.AddNode(node.Parent);
                }

            }

            int index = cacheNodes.IndexOf(node);
            if (index == -1)
            {
                cacheNodes.Add(node);
            }
            else
            {
                cacheNodes[index] = node;
            }

            node.SetDisplayOrder();
        }

        public virtual void Remove(TreeNode node)
        {
            if (this.cacheNodes.Contains(node))
            {
                ///将排序改到最大，不然直接删除会导致排序出现断层
                node.ChangeDisplayOrder(99999999);
                this.cacheNodes.Remove(node);
            }
        }

        public virtual void Update(TreeNode node)
        {
            this.AddNode(node);
        }

        private void CheckNode(TreeNode node)
        {
            if (node == null)
            {
                throw new ArgumentNullException("node");
            }

            if (!node.TreeView.Equals(this))
            {
                throw new ArgumentOutOfRangeException("node不是从当前TreeView创建的，不能添加至当前TreeView。");
            }
        }
        #endregion

        public virtual TreeNode FindNodeBy(object key)
        {
            return this.Items.FirstOrDefault(item => item.Key.ToString().Equals(key.ToString(), StringComparison.OrdinalIgnoreCase));
        }

        #region CreateNode

        public TreeNode CreateNode(ITreeNodeTag tag)
        {
            return this.CreateNode(null,tag);
        }

        public TreeNode CreateNode(TreeNode parentNode, ITreeNodeTag tag)
        {
            if (tag == null)
            {
                throw new ArgumentNullException("tag");
            }

            return new TreeNode(this, parentNode, tag);
        }

        #endregion
    }
}
